#ifndef A50A2ADC_2DEA_4111_9BC9_B09FDEE7DA5D
#define A50A2ADC_2DEA_4111_9BC9_B09FDEE7DA5D

#include <iostream>
#include <vector>
#include <pthread.h>
#include <unistd.h>
#include <queue>
#include <ctime>
#include "Task.hpp"

struct ThreadInfo
{
	pthread_t tid;
	std::string Threadname;
};

static const int defaultnum = 5;

template <class T>
class ThreadPool
{
public:
	void Lock()
	{
		pthread_mutex_lock(&mutex);
	}
	void Unlock()
	{
		pthread_mutex_unlock(&mutex);
	}
	void wake()
	{
		pthread_cond_signal(&cond);
	}
	void Threadsleep()
	{
		pthread_cond_wait(&cond, &mutex);
	}
	bool isEmpty()
	{
		return tasks_.empty();
	}
	std::string threadname(const pthread_t &tid)
	{
		for (auto &ti : threads_)
		{
			if (tid == ti.tid)
				return ti.Threadname;
		}
		return "none";
	}

public:
	ThreadPool(int num = defaultnum) : threads_(num)
	{
		pthread_mutex_init(&mutex, nullptr);
		pthread_cond_init(&cond, nullptr);
	}
	void start()
	{
		int len = threads_.size();
		for (int i = 0; i < len; i++)
		{
			pthread_t tid;
			pthread_create(&tid, nullptr, handlerTask, this);
			threads_[i].tid = tid;
			threads_[i].Threadname = "thread-" + std::to_string(i + 1);
		}
	}
	static void *handlerTask(void *args)
	{
		ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
		while (1)
		{
			tp->Lock();
			while (tp->isEmpty())
			{
				tp->Threadsleep();
			}
			T t = tp->pop();
			std::string name = tp->threadname(pthread_self());
			tp->Unlock();
			t();              ////// 处理
			// std::cout << "deal done , resulet:" << t.Getresult() << " thread name : " << name << std::endl;
			usleep(150);
		}
		return nullptr;
	}
	void push(const T &task)
	{
		Lock();
		tasks_.push(task);
		wake();
		Unlock();
	}
	T pop()
	{
		T t = tasks_.front();
		tasks_.pop();
		return t;
	}
	static ThreadPool<T>* Initializer()
	{
		if(tp_ == nullptr)
		{
			pthread_mutex_lock(&lock_);
			if(tp_ == nullptr){
				std::cout << "creatr a new ThreadPool<T>" << std::endl;
				tp_ = new ThreadPool<T>();
			}
			pthread_mutex_unlock(&lock_);
		}
		return tp_;
	}
	~ThreadPool()
	{
		pthread_mutex_destroy(&mutex);
		pthread_cond_destroy(&cond);
	}
	ThreadPool(const ThreadPool& tp) = delete;        ///////  限制单例模式
	void operator=(const ThreadPool& tp) = delete;
private:
	std::vector<ThreadInfo> threads_;
	std::queue<T> tasks_;

	pthread_mutex_t mutex;
	pthread_cond_t cond;
	static ThreadPool<T>* tp_;
	static pthread_mutex_t lock_;
};

template<class T>
ThreadPool<T>* ThreadPool<T>::tp_ = nullptr;

template<class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;

#endif /* A50A2ADC_2DEA_4111_9BC9_B09FDEE7DA5D */
